#include "variablefuncion.h"

VariableFuncion::VariableFuncion(Variable *sig, vector<Expr *> expr,int fila,int col):Variable(sig,fila,col)
{
    this->expr=expr;
}

void VariableFuncion::setExpr(vector<Expr *> expr)
{
    this->expr=expr;
}

vector<Expr *> VariableFuncion::getExpr()
{
    return this->expr;
}

string VariableFuncion::is()
{
    return "Variable_Funcion";
}

Tipo_ts *VariableFuncion::validarSemantica(Tabla_Simbolos *tabla_de_tipo, Tabla_Simbolos *tabla_de_varaible)
{
    vector<Item_ts*> its = tabla_de_varaible->getALL(this->getValor().append("&FP&"));
            if(its.size()>0){

                for(int i=0;i<(int)its.size();i++){
                    bool find = true;
                    if(its.at(i)->getTipo()->is().compare("FUNCION")==0 ){
                   Funcion *fun = (Funcion*)its.at(i)->getTipo();
                    if((int)this->getExpr().size()==fun->getParams()->getTable().size()){
                        for(int i=0;i<(int)this->getExpr().size();i++){
                            Tipo_ts *tts = this->getExpr().at(i)->validarSemantica(tabla_de_tipo,tabla_de_varaible);
                            if(tts->is().compare(fun->getParams()->getTable().at(i)->getTipo()->is()) != 0){

                                find = false;
                            }else{
                                if(fun->getParams()->getTable().at(i)->getVar()){
                                    if(this->getExpr().at(i)->is().compare("Literal_Identificador")!=0){

                                        find = false;
                                    }

                                }

                            }

                        }

                    }else{
                        find = false;
                    }

                    if(find){
                        if(fun->getTiporetorno()->is().compare("REGISTRO")==0&&this->getsig()!=0){
                            Registro *r = (Registro*)fun->getTiporetorno();
                            return this->getsig()->validarSemantica(tabla_de_tipo,r->getTs());
                        }else{
                        return fun->getTiporetorno();
                        }
                    }

                }else{
                if(its.at(i)->getTipo()->is().compare("PROCEDIMIENTO")==0 ){
                    Procedimiento *pro = (Procedimiento*)its.at(i)->getTipo();
                    if((int)this->getExpr().size()==pro->getParams()->getTable().size()){
                    for(int i=0;i<(int)this->getExpr().size();i++){
                       Tipo_ts *tts = this->getExpr().at(i)->validarSemantica(tabla_de_tipo,tabla_de_varaible);
                        if(tts->is().compare(pro->getParams()->getTable().at(i)->getTipo()->is()) != 0){

                            find = false;
                        }else{
                            if(pro->getParams()->getTable().at(i)->getVar()){
                                if(this->getExpr().at(i)->is().compare("Literal_Identificador")!=0){

                                    find = false;
                                }
                            }


                        }

                    }
                }else{
                    find = false;
                }
                    if(find){
                    return 0;
                    }
                }else{
                    stringstream out;
                    out<<"Se esperaba una funcion o un procedimiento// Fila:"<<this->getFila()<<endl;
                    throw exception(out.str().c_str());
                    }
                }
                }

                stringstream out;
                out<<"PARAMETROS DE LA FUNCION O PROCEDIMIENTO INCORRECTOS "<<this->getValor()<<" // Fila: "<<this->getFila()<<endl;
                    throw exception(out.str().c_str());


            }else{
                stringstream out;
                out<<"Variable No exite "<<this->getValor()<<" // Fila: "<<this->getFila()<<endl;
                throw exception(out.str().c_str());
            }
}

Codigo_Lugar VariableFuncion::generarCodigo(GenerarVariable *var, Tabla_Simbolos *tabla_de_tipo, Tabla_Simbolos *tabla_de_varaible)
{
    Codigo_Lugar cl;
    string codigo = "_"+this->getValor().append("&FP&")+"_(";
    for(int i=0;i<this->expr.size();i++){
        codigo+=this->expr.at(i)->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+",";
    }
    codigo = codigo.substr(0,codigo.size()-1);
    codigo+= ")";
    cl.codigo = codigo;
    return cl;

}
